package site.jlopen.service.imp;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;

import site.jlopen.assets.spring.ComponentsInit;
import site.jlopen.components.entity.GrapGroup;
import site.jlopen.components.entity.GraphJson.GraphJsonNode;
import site.jlopen.components.entity.GraphJsonUtil;
import site.jlopen.components.entity.GraphNode;
import site.jlopen.components.entity.GraphNodeAttr;
import site.jlopen.components.entity.GraphNodeInputOutput;
import site.jlopen.components.entity.GraphNodeParam;
import site.jlopen.components.entity.GraphNodeParamCopy;
import site.jlopen.components.enums.GrapGroupNameEnum;
import site.jlopen.domain.data.KusciaData;
import site.jlopen.domain.data.event.KusciaDataColumnEvent;
import site.jlopen.domain.node.event.KusciaNodeEvent;
import site.jlopen.domain.project.KusciaProjectFlow;
import site.jlopen.domain.project.KusciaProjectGraphParam;
import site.jlopen.domain.project.event.ProjectInviteNodeVO;
import site.jlopen.entity.BaseResponse;
import site.jlopen.entity.grap.RenderAttrValueInfo;
import site.jlopen.entity.grap.RenderAttrValueInfo.RenderAttrItem;
import site.jlopen.mapper.data.KusciaDataColumnMapper;
import site.jlopen.mapper.data.KusciaDataMapper;
import site.jlopen.mapper.node.KusciaNodeMapper;
import site.jlopen.mapper.project.KusciaProjectFlowMapper;
import site.jlopen.mapper.project.KusciaProjectGraphParamMapper;
import site.jlopen.mapper.project.KusciaProjectInviteMapper;
import site.jlopen.service.intf.project.GraphService;
import site.jlopen.utils.StringUtil;
import site.jlopen.utils.id.IdUtils;

@Service("GraphService")
public class GraphServiceImpl implements GraphService {
	
	@Autowired
	private KusciaProjectFlowMapper flowMapper;
	@Autowired
	private KusciaProjectGraphParamMapper graphParamMapper;
	@Autowired
	private ComponentsInit componentsInit;
	@Autowired
	private KusciaDataMapper dataMapper;
	@Autowired
	private KusciaDataColumnMapper columnMapper;
	@Autowired
	private KusciaProjectInviteMapper inviteMapper;
	@Autowired
	private KusciaNodeMapper nodeMapper;

	@Override
	public List<GrapGroup> getGrapGroup() {
		List<GrapGroup> groups = new ArrayList<GrapGroup>();
		List<GraphNodeParam> defs = componentsInit.getParams();
		Map<String, List<GraphNodeParam>> domainMap = new HashMap<String, List<GraphNodeParam>>();
		for (GraphNodeParam nodeParam : defs) {
			List<GraphNodeParam> domains = new ArrayList<GraphNodeParam>();
			if(null != domainMap.get(nodeParam.getDomain())) {
				domains.addAll(domainMap.get(nodeParam.getDomain()));
			}
			domains.add(nodeParam);
			domainMap.put(nodeParam.getDomain(), domains);
		}
		for(Map.Entry<String, List<GraphNodeParam>> entry : domainMap.entrySet()){
			  String domainName = entry.getKey();
			  List<GraphNodeParam> value = entry.getValue();
			  GrapGroup group = new GrapGroup(GrapGroupNameEnum.title(domainName), domainName);
			  for (GraphNodeParam param : value) {
				  GraphNode node = new GraphNode(param.getName(), param.getCode());
				  node.addDesc(param.getDesc());
				  node.SECRETFLOW();
				  // 如果是读取数据的组件，取消输入端
				  if(!"read_data".equals(param.getCode())) {
					  for (GraphNodeInputOutput ind : param.getInds()) {
						  node.addPort("top");
					  }
				  }
				  if(!"table_statistics".equals(param.getCode())) {
					  for (GraphNodeInputOutput outd : param.getOutds()) {
						  node.addPort("bottom");
					  }
				  }
				  group.addNode(node);
			}
			  groups.add(group);
			}
		return groups;
	}
	
	@Override
	public BaseResponse<String> saveGraph(Long flowId, String grapJson) {
		GraphJsonUtil jsonUtil = new GraphJsonUtil(grapJson);
		List<GraphJsonNode> pnodes = jsonUtil.getParentNodes();
		System.out.println(pnodes);
		KusciaProjectFlow flow = new KusciaProjectFlow();
		flow.setFlowId(flowId);
		flow.setFlowJson(grapJson);
		int row = flowMapper.updateSelective(flow);
		return new BaseResponse<String>().dbRes(row, "保存成功");
	}

	@Override
	public BaseResponse<String> loadGraph(Long flowId) {
		KusciaProjectFlow flow = flowMapper.selectByKey(flowId);
		if(null == flow) {
			return new BaseResponse<String>().error("流程不存在");
		}
		return new BaseResponse<String>().success("OK").setData(flow.getFlowJson());
	}

	@Override
	public BaseResponse<String> saveNodeAttr(GraphNodeParam param) {
		KusciaProjectFlow flow = flowMapper.selectByKey(param.getFlowId());
		GraphJsonUtil jsonUtil = new GraphJsonUtil(flow.getFlowJson());
		GraphJsonNode graphNode = jsonUtil.getNodeById(param.getGraphId());
		
		if(null == graphNode) {
			return new BaseResponse<String>().error("请先保存流程图");
		}
		KusciaProjectGraphParam paramInfo = graphParamMapper.selectByInfo(
				new KusciaProjectGraphParam().setParamFlowId(flow.getFlowId()).setParamGraphId(param.getGraphId()));
		int row = 0;
		//List<GraphNodeInputOutput> outs = param.getOutds();
		/*if("read_data".equals(param.getNodeCode())) {
			outs.get(0).setProp(param.getAttrs().get(0).getProp());
			
		}*/
		Map<String, Object> attrs = new HashMap<String, Object>();
		Map<String, Object> inds = new HashMap<String, Object>();
		for(GraphNodeAttr attr: param.getAttrs()) {
			attrs.put(attr.getCode(), StringUtil.isBlank(attr.getProp())?attr.getDefVal():attr.getProp());
		}
		/*for(GraphNodeInputOutput input: param.getInds()) {
			inds.put(input.getCode(), "id");
		}*/
		if(null == paramInfo) {
			List<String> outds = new ArrayList<String>();
			if("read_data".equals(param.getCode())) {
				outds.add(param.getAttrs().get(0).getProp());
			}else {
				for(GraphNodeInputOutput output: param.getOutds()) {
					outds.add(String.valueOf(IdUtils.SnowFlakeId()));
				}
			}
			paramInfo = new KusciaProjectGraphParam()
			.setParamId(IdUtils.SnowFlakeId())
			.setParamFlowId(flow.getFlowId())
			.setParamGraphId(param.getGraphId())
			.setParamGraphCode(param.getCode())
			.setParamAttr(JSON.toJSONString(attrs))
			.setParamInputs(JSON.toJSONString(inds))
			.setParamOutputs(JSON.toJSONString(outds))
			.setParamDef(null)
			.setParamCreate(new Date());
			/*if(null != outs) {
				for (GraphNodeInputOutput out : outs) {
					out.setProp(null);
				}
			}*/
			/*if(!"read_data".equals(param.getNodeCode())) {
				if(null != outs) {
					for (GraphNodeInputOutput out : outs) {
						out.setProp(param.getNodeId() + "-" + out.getName().replace("_", "-"));
					}
				}
			}*/
			row = graphParamMapper.insertSelective(paramInfo);
		}else {
			paramInfo
			.setParamAttr(JSON.toJSONString(attrs))
			.setParamDef(null);
			if("read_data".equals(param.getCode())) {
				List<String> outds = new ArrayList<String>();
				outds.add(param.getAttrs().get(0).getProp());
				paramInfo.setParamOutputs(JSON.toJSONString(outds));
			}
			row = graphParamMapper.updateSelective(paramInfo);
		}
		return new BaseResponse<String>().dbRes(row, "配置已保存");
	}

	@Override
	public BaseResponse<GraphNodeParam> loadNodeAttr(Long projectId, Long flowId, String graphId, String nodeCode) {
		GraphNodeParam defParam = componentsInit.getNode(nodeCode);
		if (null == defParam) {
			return new BaseResponse<GraphNodeParam>().error("原节点属性不存在");
		}
		GraphNodeParam param = new GraphNodeParamCopy().init(defParam);
		param.setGraphId(graphId);
		KusciaProjectGraphParam paramInfo = graphParamMapper.selectByInfo(
				new KusciaProjectGraphParam().setParamFlowId(flowId).setParamGraphId(graphId));
		if(null != paramInfo) {
			param.setParamId(paramInfo.getParamId());
			Map<String, Object> attrsMap = JSON.parseObject(paramInfo.getParamAttr(), new TypeReference<Map<String, Object>>() {});
			List <GraphNodeAttr> attrs = param.getAttrs();
			for(GraphNodeAttr attr: attrs) {
				if(StringUtil.isNotEmpty(attrsMap.get(attr.getCode()))) {
					attr.setProp(attrsMap.get(attr.getCode()).toString());
				}
			}
		}
		for (GraphNodeAttr attr : param.getAttrs()) {
			attr.beupload();
		}
		return new BaseResponse<GraphNodeParam>().success("SUCCESS").setData(param);
	}

	@Override
	public BaseResponse<RenderAttrValueInfo> renderAttrValue(Long projectId, Long flowId, String graphId, String nodeCode, String attrCode) {
		RenderAttrValueInfo value = new RenderAttrValueInfo();
		GraphNodeParam defParam = componentsInit.getNode(nodeCode);
		if (null == defParam) {
			return new BaseResponse<RenderAttrValueInfo>().error("节点属性不存在");
		}
		GraphNodeParam param = new GraphNodeParamCopy().init(defParam);
		value.setLimit(1);
		value.setType("NON");
		List <RenderAttrValueInfo.RenderAttrItem> items = new ArrayList<RenderAttrValueInfo.RenderAttrItem>();
		List<GraphNodeAttr> attrs = param.getAttrs();
		if(null != attrs && attrs.size() > 0) {
			for (GraphNodeAttr attr : attrs) {
				if(attr.getCode().equals(attrCode)) {
					if(attr.getType().equals("ss")) {
						value.setLimit(100);
					}
					value.setDesc(attr.getDesc());
				}
			}
		}
		/**
		 * 开始自定义参数内容
		 */
		switch (nodeCode) {
		case "read_data": {
			//读取数据
			value.setType("SELECT");
			List<KusciaData> datas=  dataMapper.selectInviteDatas(projectId);
			for (KusciaData data : datas) {
				items.add(new RenderAttrItem(data.getDataTitle(), data.getDataDomaindataId()));
			}
			break;
		}
		case "psi": {
			//隐私求交
			if(attrCode.equals("input/sender_input/key") || attrCode.equals("input/receiver_input/key")) {
				value.setType("GROUP");
				List<KusciaData> datas=  dataMapper.selectInviteDatas(projectId);
				for (KusciaData data : datas) {
					RenderAttrItem item = new RenderAttrItem(data.getDataTitle());
					Map<String, Object> cmap = new HashMap<String, Object>();
					cmap.put("columnDataId", data.getDataId());
					List<KusciaDataColumnEvent> cList = columnMapper.selectAllNotPage(cmap);
					for (KusciaDataColumnEvent column : cList) {
						item.addOption(column.getColumnName(), column.getColumnName());
					}
					items.add(item);
				}
			}
			if(attrCode.equals("allow_duplicate_keys/yes/join_type/left_join/left_side")) {
				value.setType("SELECT");
				List<ProjectInviteNodeVO> invites = inviteMapper.selectInviteNodes(projectId);
				for (ProjectInviteNodeVO invite : invites) {
					if("owner".equals(invite.getRole())) {
						KusciaNodeEvent node = nodeMapper.selectByKey(invite.getNodeId());
						items.add(new RenderAttrItem(node.getNodeTitle(), node.getNodeCode()));
					}
				}
			}
			break;
		}
		case "table_statistics": {
			//全表统计
			value.setType("GROUP");
			List<KusciaData> datas=  dataMapper.selectInviteDatas(projectId);
			for (KusciaData data : datas) {
				RenderAttrItem item = new RenderAttrItem(data.getDataTitle());
				Map<String, Object> cmap = new HashMap<String, Object>();
				cmap.put("columnDataId", data.getDataId());
				List<KusciaDataColumnEvent> cList = columnMapper.selectAllNotPage(cmap);
				for (KusciaDataColumnEvent column : cList) {
					item.addOption(column.getColumnName(), column.getColumnName());
				}
				items.add(item);
			}
			break;
		}
		/*case "union": {
			//纵向联邦表
			break;
		}*/
		/*case "train_test_split": {
			//随机分割
			break;
		}*/
		default:
		}
		value.setItems(items);
		return new BaseResponse<RenderAttrValueInfo>().success("SUCCESS").setData(value);
	}
}
